using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Matrix.Configuration.Services;
using Matrix.Configuration.Events;

namespace Matrix.Configuration.Extensions
{
    /// <summary>
    /// 配置服务扩展方法
    /// 提供IOptionsMonitor模式的配置热更新功能
    /// </summary>
    public static class ConfigurationServiceExtensions
    {
        /// <summary>
        /// 添加Matrix配置热更新服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddMatrixConfigurationHotReload(this IServiceCollection services)
        {
            // 注册配置监控器和通知器
            services.AddSingleton<IConfigurationWatcher, MatrixConfigurationMonitor>();
            services.AddSingleton<IConfigurationChangeNotifier, MatrixConfigurationMonitor>();

            // 配置选项
            services.AddOptions<ConfigurationOptions>()
                .Configure<IServiceProvider>((options, serviceProvider) =>
                {
                    // 可以在这里从其他配置源加载选项
                });

            return services;
        }

        /// <summary>
        /// 添加Matrix配置热更新服务并配置选项
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configureOptions">配置选项委托</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddMatrixConfigurationHotReload(
            this IServiceCollection services,
            Action<ConfigurationOptions>? configureOptions = null)
        {
            services.AddMatrixConfigurationHotReload();

            if (configureOptions != null)
            {
                services.Configure(configureOptions);
            }

            return services;
        }

        /// <summary>
        /// 启动配置监控
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>启动任务</returns>
        public static async Task StartConfigurationMonitoringAsync(
            this IServiceProvider serviceProvider,
            CancellationToken cancellationToken = default)
        {
            var watcher = serviceProvider.GetRequiredService<IConfigurationWatcher>();
            await watcher.StartWatchingAsync(cancellationToken);
        }

        /// <summary>
        /// 停止配置监控
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        /// <returns>停止任务</returns>
        public static async Task StopConfigurationMonitoringAsync(this IServiceProvider serviceProvider)
        {
            var watcher = serviceProvider.GetRequiredService<IConfigurationWatcher>();
            await watcher.StopWatchingAsync();
        }

        /// <summary>
        /// 订阅配置变更
        /// </summary>
        /// <typeparam name="T">配置类型</typeparam>
        /// <param name="serviceProvider">服务提供者</param>
        /// <param name="key">配置键</param>
        /// <param name="callback">变更回调</param>
        /// <param name="namespace">命名空间</param>
        /// <returns>订阅ID</returns>
        public static IDisposable SubscribeToConfigurationChange<T>(
            this IServiceProvider serviceProvider,
            string key,
            Action<ConfigurationChangedEventArgs<T>> callback,
            string? @namespace = null)
        {
            var notifier = serviceProvider.GetRequiredService<IConfigurationChangeNotifier>();
            return notifier.SubscribeOnChange(key, @namespace, callback);
        }

        /// <summary>
        /// 订阅配置变更
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        /// <param name="key">配置键</param>
        /// <param name="callback">变更回调</param>
        /// <param name="namespace">命名空间</param>
        /// <returns>订阅ID</returns>
        public static IDisposable SubscribeToConfigurationChange(
            this IServiceProvider serviceProvider,
            string key,
            Action<ConfigurationChangedEventArgs> callback,
            string? @namespace = null)
        {
            var notifier = serviceProvider.GetRequiredService<IConfigurationChangeNotifier>();
            return notifier.SubscribeOnChange(key, @namespace, callback);
        }

        /// <summary>
        /// 获取当前配置值
        /// </summary>
        /// <typeparam name="T">配置类型</typeparam>
        /// <param name="serviceProvider">服务提供者</param>
        /// <param name="key">配置键</param>
        /// <param name="namespace">命名空间</param>
        /// <returns>配置值</returns>
        public static async Task<T?> GetConfigurationAsync<T>(
            this IServiceProvider serviceProvider,
            string key,
            string? @namespace = null)
        {
            var notifier = serviceProvider.GetRequiredService<IConfigurationChangeNotifier>();
            return await notifier.GetCurrentAsync<T>(key, @namespace);
        }

        /// <summary>
        /// 批量订阅配置变更
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        /// <param name="subscriptions">订阅配置列表</param>
        /// <returns>订阅ID列表</returns>
        public static async Task<List<IDisposable>> SubscribeToConfigurationChangesBatchAsync(
            this IServiceProvider serviceProvider,
            List<ConfigurationSubscriptionDefinition> subscriptions)
        {
            var notifier = serviceProvider.GetRequiredService<IConfigurationChangeNotifier>();
            var watcher = serviceProvider.GetRequiredService<IConfigurationWatcher>();
            var disposables = new List<IDisposable>();

            foreach (var subscription in subscriptions)
            {
                // 添加到监控列表
                watcher.AddWatchKey(subscription.Key, subscription.Namespace);

                // 订阅变更通知
                IDisposable disposable;

                if (subscription.IsTyped)
                {
                    var method = typeof(IConfigurationChangeNotifier)
                        .GetMethod(nameof(IConfigurationChangeNotifier.SubscribeOnChange))
                        ?.MakeGenericMethod(subscription.ValueType!);

                    if (method != null)
                    {
                        disposable = (IDisposable)method.Invoke(notifier, new object[]
                        {
                            subscription.Key,
                            subscription.Namespace,
                            ConvertDelegateToAction(subscription.Callback, subscription.ValueType!)
                        });
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    disposable = notifier.SubscribeOnChange(subscription.Key, subscription.Namespace,
                        (Action<ConfigurationChangedEventArgs>)subscription.Callback);
                }

                disposables.Add(disposable);
            }

            return disposables;
        }

        private static object ConvertDelegateToAction(Delegate callback, Type valueType)
        {
            var typedEventArgsType = typeof(ConfigurationChangedEventArgs<>).MakeGenericType(valueType);
            var actionType = typeof(Action<>).MakeGenericType(typedEventArgsType);
            return Delegate.CreateDelegate(actionType, callback.Method);
        }
    }

    /// <summary>
    /// 配置订阅定义
    /// </summary>
    public class ConfigurationSubscriptionDefinition
    {
        /// <summary>
        /// 配置键
        /// </summary>
        public string Key { get; set; } = string.Empty;

        /// <summary>
        /// 命名空间
        /// </summary>
        public string? Namespace { get; set; }

        /// <summary>
        /// 是否为类型化订阅
        /// </summary>
        public bool IsTyped { get; set; }

        /// <summary>
        /// 值类型
        /// </summary>
        public Type? ValueType { get; set; }

        /// <summary>
        /// 回调委托
        /// </summary>
        public Delegate Callback { get; set; } = null!;

        /// <summary>
        /// 描述
        /// </summary>
        public string? Description { get; set; }

        /// <summary>
        /// 创建类型化订阅定义
        /// </summary>
        /// <typeparam name="T">配置类型</typeparam>
        /// <param name="key">配置键</param>
        /// <param name="callback">回调</param>
        /// <param name="namespace">命名空间</param>
        /// <param name="description">描述</param>
        /// <returns>订阅定义</returns>
        public static ConfigurationSubscriptionDefinition Create<T>(
            string key,
            Action<ConfigurationChangedEventArgs<T>> callback,
            string? @namespace = null,
            string? description = null)
        {
            return new ConfigurationSubscriptionDefinition
            {
                Key = key,
                Namespace = @namespace,
                IsTyped = true,
                ValueType = typeof(T),
                Callback = callback,
                Description = description
            };
        }

        /// <summary>
        /// 创建通用订阅定义
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="callback">回调</param>
        /// <param name="namespace">命名空间</param>
        /// <param name="description">描述</param>
        /// <returns>订阅定义</returns>
        public static ConfigurationSubscriptionDefinition Create(
            string key,
            Action<ConfigurationChangedEventArgs> callback,
            string? @namespace = null,
            string? description = null)
        {
            return new ConfigurationSubscriptionDefinition
            {
                Key = key,
                Namespace = @namespace,
                IsTyped = false,
                ValueType = typeof(object),
                Callback = callback,
                Description = description
            };
        }
    }

    /// <summary>
    /// 配置热更新构建器
    /// </summary>
    public class ConfigurationHotReloadBuilder
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly List<ConfigurationSubscriptionDefinition> _subscriptions = new();

        public ConfigurationHotReloadBuilder(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 添加配置订阅
        /// </summary>
        /// <typeparam name="T">配置类型</typeparam>
        /// <param name="key">配置键</param>
        /// <param name="callback">回调</param>
        /// <param name="namespace">命名空间</param>
        /// <returns>构建器</returns>
        public ConfigurationHotReloadBuilder Subscribe<T>(
            string key,
            Action<ConfigurationChangedEventArgs<T>> callback,
            string? @namespace = null)
        {
            _subscriptions.Add(ConfigurationSubscriptionDefinition.Create(key, callback, @namespace));
            return this;
        }

        /// <summary>
        /// 添加配置订阅
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="callback">回调</param>
        /// <param name="namespace">命名空间</param>
        /// <returns>构建器</returns>
        public ConfigurationHotReloadBuilder Subscribe(
            string key,
            Action<ConfigurationChangedEventArgs> callback,
            string? @namespace = null)
        {
            _subscriptions.Add(ConfigurationSubscriptionDefinition.Create(key, callback, @namespace));
            return this;
        }

        /// <summary>
        /// 构建并启动所有订阅
        /// </summary>
        /// <returns>订阅ID列表</returns>
        public async Task<List<IDisposable>> BuildAsync()
        {
            return await _serviceProvider.SubscribeToConfigurationChangesBatchAsync(_subscriptions);
        }

        /// <summary>
        /// 清除所有订阅
        /// </summary>
        public ConfigurationHotReloadBuilder Clear()
        {
            _subscriptions.Clear();
            return this;
        }

        /// <summary>
        /// 获取订阅数量
        /// </summary>
        public int Count => _subscriptions.Count;
    }

    /// <summary>
    /// 配置热更新扩展方法
    /// </summary>
    public static class ConfigurationHotReloadExtensions
    {
        /// <summary>
        /// 创建配置热更新构建器
        /// </summary>
        /// <param name="serviceProvider">服务提供者</param>
        /// <returns>构建器</returns>
        public static ConfigurationHotReloadBuilder CreateConfigurationHotReloadBuilder(
            this IServiceProvider serviceProvider)
        {
            return new ConfigurationHotReloadBuilder(serviceProvider);
        }
    }
}